#pragma once
#include "dll_export.h"
#include "DebugEvent.h"
#include "../cppx.luavm/Breakpoint.h"
#include "../cppx.luavm/RemoteEngine.h"

LUA_DEBUG_BEGIN

class fbpMainFrame;

class _LUADBG_API Mediator
{
    RemoteEngine_ptr     m_engine;
    BreakpointList       m_breakpoints;
    SourceManager        m_sourceManager;
    queue_mt<LuaCommand> m_readCommands;
    LuaStackFrame        m_stackFrame;
    int                  m_updateCount;
    fbpMainFrame *       m_frame;

public:
    Mediator(void);
    ~Mediator(void);

    /// Get the RemoteEngine object.
    RemoteEngine_ptr GetEngine() {
        return m_engine;
    }

    /// Get the main frame.
    fbpMainFrame *GetFrame() {
        return m_frame;
    }

    /// Set the main frame.
    void SetMainFrame(fbpMainFrame *frame){
        m_frame = frame;
    }

    /// Get the BreakpointList object.
    BreakpointList &GetBreakpoints() {
        return m_breakpoints;
    }

    /// Get the SourceManager object.
    SourceManager &GetSourceManager() {
        return m_sourceManager;
    }

    /// Get the source contents.
    const Source *GetSource(const std::string &key) {
        return m_sourceManager.Get(key);
    }

    /// Find the breakpoint.
    Breakpoint FindBreakpoint(const std::string &key, int line) {
        return m_breakpoints.Find(key, line);
    }

    /// Find the next breakpoint.
    Breakpoint NextBreakpoint(const Breakpoint &bp) {
        return m_breakpoints.Next(bp);
    }

    /// Set the breakpoint.
    void SetBreakpoint(const Breakpoint &bp) {
        m_breakpoints.Set(bp);
    }

    /// Toggle on/off of the breakpoint.
    void ToggleBreakpoint(const std::string &key, int line) {
        m_breakpoints.Toggle(key, line);
    }

    /// Get the stack frame for the local vars.
    const LuaStackFrame &GetStackFrame() {
        return m_stackFrame;
    }

    /// Set the stack frame for the local vars.
    void SetStackFrame(const LuaStackFrame &stackFrame) {
        m_stackFrame = stackFrame;
    }

    /// Get the count of 'UpdateSource'.
    int GetUpdateCount() {
        return m_updateCount;
    }

    /// Increment the update count.
    void IncUpdateCount() {
        ++m_updateCount;
        m_engine->SendSetUpdateCount(m_updateCount);
    }

    void ProcessAllRemoteCommands(void);

private:
    void OnRemoteCommand(LuaCommand &command);
    void ProcessRemoteCommand(const LuaCommand &command);
    void ProcessDebugEvent(wxDebugEvent & event);
};

typedef boost::shared_ptr<Mediator> Mediator_ptr;

LUA_DEBUG_END
